/* Copyright:       lielie4780
 * Author:          孙强 <1604070358@qq.com>
 * Tags:            Qt CMake C++ Sqlite
 * Repo:            https://gitee.com/lielie4780/cpp_design
 * License:         MIT
 * Description:     面向对象程序设计（C++）课程设计项目，题目为：图书管理系统
 * */
#include <QApplication>
#include <QDebug>
#include <QFile>
#include <QMessageBox>

#include "Database.h"
#include "loginwindow.h"
#include "mainwindow.h"

int main(int argc, char *argv[]) {
    int exitCode;  // 记录程序结束状态，为了退出登录的功能加上的变量

    // 程序主体逻辑
    do {
        // 删除掉失效的数据文件，为了保险
        // 数据文件用来记录登录用户的信息，为了更好地在登录页面和主窗口传递数据
        // 槽函数和信号使用起来不是特别方便，没有办法传递复杂的数据
        QFile loginFile("./login.ini");
        if (loginFile.exists()) {
            loginFile.remove();
        }

        // 这一行是删除掉原来的数据库文件，用于测试初始化数据库的功能
        // 之后这一行会被注释掉
        // 这里不用重新创建数据库文件，在打开数据库的时候就会自动创建
        QFile dbFile("./library.db");
//        if (dbFile.exists()) {
//            dbFile.remove();
//        }

        QApplication application(argc, argv);

        // 检查数据库完整性/初始化数据
        // 使用sqlite数据库，不用mysql数据库，这样就省去了用户安装mysql和创建数据库/表的过程

        if (!dbFile.exists()) {
            // 创建数据库
            Database *database = Database::getInstance();
            database->connectDatabase();
            database->openDatabase();

            // 这一行是用来作死的
            // database->closeDatabase();
            if (!database->isDatabaseOpen()) {
                // 如果数据库没法打开的话，就显示一个错误的对话框，之后结束程序
                QMessageBox::critical(nullptr, "错误", "数据库无法打开！");
                return 0;
                // 这里还有一种写法 QApplication::exit();
                // 但是之后的登录页面会一闪而过，不是特别好看
                // 具体的逻辑我也不太清楚，可能和模态对话框/非模态对话框有关
            }

            // 创建数据表，就是写SQL，4个分别是学生、图书、借书和管理员的表格
            QString createTableQuery[4];
            createTableQuery[0] =
                "create table student_info("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"  // id，用作主键，下同
                "name VARCHAR(15) DEFAULT 'Student',"  // 姓名
                "account VARCHAR(8) UNIQUE NOT NULL,"  // 账号
                "password VARCHAR(15) NOT NULL,"       // 密码
                "sex TINYINT NOT NULL DEFAULT 2,"   // 性别，0男1女2未知
                "borrow_book TINYINT DEFAULT 0);";  // 借阅图书数量

            createTableQuery[1] =
                "create table book_info("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "book_name VARCHAR(30) NOT NULL,"            // 图书名称
                "book_domain VARCHAR(15) NOT NULL,"          // 专业领域
                "book_number VARCHAR(15) UNIQUE NOT NULL,"   // 图书编号
                "book_price DECIMAL(7,2) NOT NULL,"          // 图书价格
                "book_author VARCHAR(30) NOT NULL,"          // 作者
                "book_publish VARCHAR(30) NOT NULL,"         // 出版社
                "book_date VARCHAR(40) NOT NULL,"            // 出版时间
                "is_borrowed BOOLEAN NOT NULL DEFAULT 0);";  // 是否被借出

            /* 下面使用外键有两个原因
             * 第一，我不知道怎么用别的方法代替外键
             * 第二，数据量不会特别大，没有必要
             */
            createTableQuery[2] =
                "create table borrow_info("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "book_number VARCHAR(15) UNIQUE NOT NULL,"     // 图书编号
                "book_name VARCHAR(30) NOT NULL,"              // 图书名称
                "student_account VARCHAR(8) NOT NULL,"  // 学生账号
                "student_name VARCHAR(15) DEFAULT 'Student',"  // 学生姓名
                "borrow_time VARCHAR(50) NOT NULL);";          // 借阅时间

            createTableQuery[3] =
                "create table admin_info("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "account VARCHAR(15) UNIQUE NOT NULL,"  // 管理员账号
                "password VARCHAR(15) NOT NULL);";      // 管理员密码
            for (const auto &i : createTableQuery) {
                if (!database->exec(i)) {
                    // 判断是否执行成功
                    QMessageBox::critical(nullptr, "错误", "数据表创建失败");
                    return 0;
                }
            }

            // 写入第一个管理员信息
            if (!database->exec("INSERT INTO admin_info VALUES("
                                "null, 'root', 'root');")) {
                QMessageBox::critical(nullptr, "错误", "数据初始化失败");
                return 0;
            }
        }
        qDebug() << "数据库准备工作完成";

        // 显示登录页面，进行用户登录的逻辑
        // 如果登录成功，不做任何行为，继续
        // 如果不登录（退出登录页面），程序直接退出
        LoginWindow loginWindow;
        if (loginWindow.exec() == QDialog::Rejected) {
            return 0;
        }

        // 登录成功，就显示主页面，由主页面加载当前登录用户的数据
        MainWindow mainWindow;
        mainWindow.show();
        exitCode = QApplication::exec();
    } while (exitCode ==
             MainWindow::exitCode); /* 这里一定要是等于号，不然逻辑就错了 */

    return exitCode;
}
